import type { FormInstance } from "element-plus"
import { ref } from "vue"

/**
 * 对话框信息封装
 */
interface DialogInfo {
    // 对话框状态，true：显示，false：隐藏
    show: boolean
    // 对话框标题
    title: string
    // 是否禁用dialog中的表单
    disable: boolean
}

/**
 * 
 * @param onHideCallback 对话框隐藏后的回调
 * @returns showDialog：显示对话框的方法
 *          hideDialog：隐藏对话框的方法
 *          submitFormData：提交表单信息的方法
 *          dialogInfo：对话框信息
 *          formInfo：表单信息
 *          formInstance：表单对象
 */
export const useFormDialog = <FORMINFO>(
    onHideCallback: () => any
) => {
    // 对话框信息
    const dialogInfo = ref<DialogInfo>({
        show: false,
        title: '',
        disable: false
    })
    // 表单信息
    const formInfo = ref<FORMINFO>({} as any)
    // 提交表单时执行方法
    let submitFunction: () => Promise<any>
    // 表单组件对象
    const formInstance = ref<FormInstance>()

    /**
     * 显示Dialog
     * @param title Dialog标题
     * @param initData 表单初始信息，该信息中的内容会合并进整个表单信息的响应式中
     * @param submitCallback 点击确定时执行的方法，如果不传递，则默认该表单仅展示不可修改
     */
    const showDialog = async (
        title: string,
        initData: FORMINFO | Promise<FORMINFO> | undefined,
        submitCallback?: () => Promise<any>
    ) => {
        formInstance.value?.resetFields()
        dialogInfo.value.title = title
        if (submitCallback) {
            submitFunction = submitCallback
            dialogInfo.value.disable = false
        } else {
            dialogInfo.value.disable = true
        }
        dialogInfo.value.show = true

        // 等待异步任务执行完
        formInfo.value = await initData ?? {}   // 若initData为null，则在外部使用formInfo获取值时会报空指针，因此在这里给默认空对象，防止空指针异常
    }

    // 隐藏Dialog
    const hideDialog = () => {
        dialogInfo.value.show = false
        formInfo.value = {} as FORMINFO
        // 重置表单的所有字段到初始值
        formInstance.value?.resetFields()
        onHideCallback()
    }

    /**
     * 提交表单
     * @param hideDialogAfterSubmit true：提交表单后隐藏对话框；false：提交表单后不隐藏对话框。默认为true
     * @returns 
     */
    const submitFormData = async (hideDialogAfterSubmit: boolean = true) => {
        // 表单校验，失败会抛出异常
        await formInstance.value?.validate()

        let result = submitFunction ? await submitFunction() : undefined

        if (hideDialogAfterSubmit) {
            hideDialog()
        }

        return result
    }

    return {
        /**
         * 显示对话框
         */
        showDialog,
        /**
         * 隐藏对话框
         */
        hideDialog,
        /**
         * 提交表单信息
         */
        submitFormData,
        /**
         * 对话框一些状态信息
         */
        dialogInfo,
        /**
         * 对话框中的表单信息
         */
        formInfo,
        /**
         * 对话框中Form表单组件对象
         */
        formInstance
    }
}